import * as vscode from 'vscode';
import * as path from 'path';
import { MAGIC_RESOURCE_TYPES, MagicResourceType } from '../types';

/**
 * 镜像文件工具类
 * 处理文件系统相关的通用操作
 */
export class MirrorFileUtils {
    private toPosix(rel: string): string {
        return rel.replace(/\\/g, '/');
    }

    private getExtForType(type: MagicResourceType): string {
        return type === 'datasource' ? '.json' : '.ms';
    }

    // 确保目录存在
    public async ensureDir(uri: vscode.Uri): Promise<void> {
        try {
            await vscode.workspace.fs.stat(uri);
        } catch {
            await vscode.workspace.fs.createDirectory(uri);
        }
    }

    // 列出本地所有 .ms 文件
    public async listLocalMsFiles(mirrorRoot: vscode.Uri): Promise<Array<{ type: MagicResourceType; dir: string; groupPathSub: string; fileName: string }>> {
        const result: Array<{ type: MagicResourceType; dir: string; groupPathSub: string; fileName: string }> = [];
        // 遍历顶层类型目录
        for (const t of MAGIC_RESOURCE_TYPES) {
            const tRoot = vscode.Uri.joinPath(mirrorRoot, t);
            let entries: [string, vscode.FileType][] = [];
            try { entries = await vscode.workspace.fs.readDirectory(tRoot); } catch { continue; }
            // 深度优先遍历
            const stack: { base: vscode.Uri; segs: string[] }[] = [{ base: tRoot, segs: [] }];
            while (stack.length) {
                const cur = stack.pop()!;
                let items: [string, vscode.FileType][] = [];
                try { items = await vscode.workspace.fs.readDirectory(cur.base); } catch { continue; }
                for (const [name, type] of items) {
                    if (type === vscode.FileType.Directory) {
                        stack.push({ base: vscode.Uri.joinPath(cur.base, name), segs: [...cur.segs, name] });
                    } else if (type === vscode.FileType.File) {
                        const ext = this.getExtForType(t);
                        if (name.endsWith(ext)) {
                            const fileName = name.slice(0, -ext.length);
                            const groupPathSub = cur.segs.join('/');
                            const dir = `${t}${groupPathSub ? '/' + groupPathSub : ''}`;
                            result.push({ type: t, dir, groupPathSub, fileName });
                        }
                    }
                }
            }
        }
        return result;
    }

    // 解析镜像工作区内文件的相对信息
    public parseMirrorFile(mirrorRoot: vscode.Uri, fileUri: vscode.Uri): { type: MagicResourceType | null; groupPathSub: string; fileName: string | null; typedPath: string | null } {
        const rel = path.relative(mirrorRoot.path, fileUri.path);
        const segs = rel.split(path.sep).filter(Boolean);
        const last = segs[segs.length - 1] || '';
        const typeIndex = segs.findIndex(s => (MAGIC_RESOURCE_TYPES as readonly string[]).includes(s));
        const type = (typeIndex >= 0 ? segs[typeIndex] : '') as MagicResourceType;
        const isValidType = !!type && (MAGIC_RESOURCE_TYPES as readonly string[]).includes(type);
        const ext = isValidType ? this.getExtForType(type) : '.ms';
        const isScriptFile = last.endsWith(ext);
        const fileName = isScriptFile ? last.slice(0, -ext.length) : null;
        const groupStart = typeIndex >= 0 ? typeIndex + 1 : 1;
        const groupPathSub = segs.slice(groupStart, fileName ? segs.length - 1 : segs.length).join('/');
        const typedPath = (isValidType && fileName) ? `${type}${groupPathSub ? '/' + groupPathSub : ''}/${fileName}${ext}` : null;
        return { type: isValidType ? type : null, groupPathSub, fileName, typedPath };
    }

    // 根据任意文件 URI 查找其所在镜像工作区根目录
    public async findMirrorRootForUri(uri: vscode.Uri): Promise<vscode.Uri | null> {
        if (uri.scheme !== 'file') return null;
        // 自底向上查找 .magic-api-mirror.json（限制最多向上30层）
        let current = uri;
        const maxDepth = 30;
        for (let i = 0; i < maxDepth; i++) {
            try {
                const marker = vscode.Uri.joinPath(current, '.magic-api-mirror.json');
                await vscode.workspace.fs.stat(marker);
                return current;
            } catch(e) {console.warn(e)}
            const parent = vscode.Uri.joinPath(current, '..');
            if (parent.fsPath === current.fsPath) break;
            current = parent;
        }
        return null;
    }

    // 扫描当前工作区，查找所有镜像根目录（支持镜像文件夹在工作区的子目录的场景）
    public async findAllMirrorRootsInWorkspace(): Promise<vscode.Uri[]> {
        const results: vscode.Uri[] = [];
        const folders = vscode.workspace.workspaceFolders || [];
        const maxDepth = 3;
        const skip = new Set(['node_modules', '.git', '.vscode', 'build', 'out', 'dist', 'target']);

        const scanDir = async (base: vscode.Uri, depth: number): Promise<void> => {
            if (depth > maxDepth) return;
            try {
                // 如果当前目录有标记文件则加入
                const marker = vscode.Uri.joinPath(base, '.magic-api-mirror.json');
                try {
                    await vscode.workspace.fs.stat(marker);
                    results.push(base);
                    // 找到即可不再深入该分支
                    return;
                } catch(e) {console.warn(e)}

                const entries = await vscode.workspace.fs.readDirectory(base);
                for (const [name, type] of entries) {
                    if (type === vscode.FileType.Directory) {
                        if (skip.has(name)) continue;
                        await scanDir(vscode.Uri.joinPath(base, name), depth + 1);
                    } else if (type === vscode.FileType.File && name === '.magic-api-mirror.json') {
                        results.push(base);
                    }
                }
            } catch {
                // 读取失败则忽略
            }
        };

        for (const folder of folders) {
            await scanDir(folder.uri, 0);
        }
        return results;
    }
}